package com.hk.core.jdbc.query;

import com.hk.commons.util.StringUtils;
import com.hk.commons.util.date.DatePattern;
import com.hk.commons.util.date.DateTimeUtils;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.Setter;

import java.time.DayOfWeek;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.TemporalAdjusters;
import java.util.*;

/**
 * @author kevin
 * @date 2018-09-19 11:05
 */
@Setter
@Getter
@NoArgsConstructor
public class DateRangeCondition implements Condition {

    @Getter
    @RequiredArgsConstructor
    public enum DateRange {
        /**
         * today
         */
        TD("date.today"),

        /**
         * last day
         */
        YD("date.yesterday"),

        /**
         * this week
         */
        TW("date.thisweek"),

        /**
         * last week
         */
        LW("date.lastweek"),

        /**
         * this month
         */
        TM("date.thismonth"),

        /**
         * last month
         */
        LM("date.lastmonth"),

        /**
         * custom
         */
        CUSTOM("date.custom");

        private final String value;
    }

    private DateRange range;

    private String field;

    private String start;

    private String end;

    @Override
    public String toSqlString(Parametric parametric, List<Object> parameters) {
        if (Objects.isNull(range)) {
            return null;
        }
        var now = LocalDateTime.now();
        var startDate = DateTimeUtils.getLocalDateTimeStart(now); // 当天开始时间
        var endDate = DateTimeUtils.getLocalDateTimeEnd(now); //当天结束时间
        switch (range) {
            case TD -> {
                startDate = DateTimeUtils.getLocalDateTimeStart(now);
                endDate = DateTimeUtils.getLocalDateTimeEnd(now);
            }
            case YD -> {
                startDate = startDate.minusDays(1);
                endDate = endDate.minusDays(1);
            }
            case TW ->
                    startDate = startDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)).with(LocalTime.MIN); //周一凌晨
            case LW -> {
                startDate = startDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)).with(LocalTime.MIN).minusDays(7); // 上周一凌晨
                endDate = endDate.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY)).with(LocalTime.MAX).minusDays(7);// 上周日结束时间
            }
            case TM -> startDate = startDate.with(TemporalAdjusters.firstDayOfMonth()).with(LocalTime.MIN); // 本月开始时间
            case LM -> {
                var minusMonths = startDate.minusMonths(1);
                startDate = minusMonths.with(TemporalAdjusters.firstDayOfMonth()).with(LocalTime.MIN); // 上月开始时间
                endDate = minusMonths.with(TemporalAdjusters.lastDayOfMonth()).with(LocalTime.MAX);  // 上月结束时间
            }
            default -> {
                if (StringUtils.isNotEmpty(this.start)) {
                    startDate = DateTimeUtils.stringToLocalDateTime(this.start, DatePattern.YYYY_MM_DD, DatePattern.YYYY_MM_DD_HH_MM_SS);
                }
                if (StringUtils.isNotEmpty(this.end)) {
                    endDate = DateTimeUtils.stringToLocalDateTime(this.end, DatePattern.YYYY_MM_DD, DatePattern.YYYY_MM_DD_HH_MM_SS);
                }
            }
        }
        var condition = new RangeCondition<>(field, startDate, endDate, true, false);
        return condition.toSqlString(parametric, parameters);
    }
}
